{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:#777777;background-color:#ffffff;font-size:12px;text-align:right;\">\n",
    "\tprepared by Abuzer Yakaryilmaz (QuSoft@Riga) | November 07, 2018\n",
    "</div>\n",
    "<table><tr><td><i> I have some macros here. If there is a problem with displaying mathematical formulas, please run me to load these macros.</i></td></td></table>\n",
    "$ \\newcommand{\\bra}[1]{\\langle #1|} $\n",
    "$ \\newcommand{\\ket}[1]{|#1\\rangle} $\n",
    "$ \\newcommand{\\braket}[2]{\\langle #1|#2\\rangle} $\n",
    "$ \\newcommand{\\inner}[2]{\\langle #1,#2\\rangle} $\n",
    "$ \\newcommand{\\biginner}[2]{\\left\\langle #1,#2\\right\\rangle} $\n",
    "$ \\newcommand{\\mymatrix}[2]{\\left( \\begin{array}{#1} #2\\end{array} \\right)} $\n",
    "$ \\newcommand{\\myvector}[1]{\\mymatrix{c}{#1}} $\n",
    "$ \\newcommand{\\myrvector}[1]{\\mymatrix{r}{#1}} $\n",
    "$ \\newcommand{\\mypar}[1]{\\left( #1 \\right)} $\n",
    "$ \\newcommand{\\mybigpar}[1]{ \\Big( #1 \\Big)} $\n",
    "$ \\newcommand{\\sqrttwo}{\\frac{1}{\\sqrt{2}}} $\n",
    "$ \\newcommand{\\dsqrttwo}{\\dfrac{1}{\\sqrt{2}}} $\n",
    "$ \\newcommand{\\onehalf}{\\frac{1}{2}} $\n",
    "$ \\newcommand{\\donehalf}{\\dfrac{1}{2}} $\n",
    "$ \\newcommand{\\hadamard}{ \\mymatrix{rr}{ \\sqrttwo & \\sqrttwo \\\\ \\sqrttwo & -\\sqrttwo }} $\n",
    "$ \\newcommand{\\vzero}{\\myvector{1\\\\0}} $\n",
    "$ \\newcommand{\\vone}{\\myvector{0\\\\1}} $\n",
    "$ \\newcommand{\\vhadamardzero}{\\myvector{ \\sqrttwo \\\\  \\sqrttwo } } $\n",
    "$ \\newcommand{\\vhadamardone}{ \\myrvector{ \\sqrttwo \\\\ -\\sqrttwo } } $\n",
    "$ \\newcommand{\\myarray}[2]{ \\begin{array}{#1}#2\\end{array}} $\n",
    "$ \\newcommand{\\X}{ \\mymatrix{cc}{0 & 1 \\\\ 1 & 0}  } $\n",
    "$ \\newcommand{\\Z}{ \\mymatrix{rr}{1 & 0 \\\\ 0 & -1}  } $\n",
    "$ \\newcommand{\\Htwo}{ \\mymatrix{rrrr}{ \\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2} \\\\ \\frac{1}{2} & -\\frac{1}{2} & \\frac{1}{2} & -\\frac{1}{2} \\\\ \\frac{1}{2} & \\frac{1}{2} & -\\frac{1}{2} & -\\frac{1}{2} \\\\ \\frac{1}{2} & -\\frac{1}{2} & -\\frac{1}{2} & \\frac{1}{2} } } $\n",
    "$ \\newcommand{\\CNOT}{ \\mymatrix{cccc}{1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0} } $\n",
    "$ \\newcommand{\\norm}[1]{ \\left\\lVert #1 \\right\\rVert } $"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2> <font color=\"blue\"> Solutions for </font>Two Qubits</h2>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"task1\"></a>\n",
    "<h3> Task 1 </h3>\n",
    "\n",
    "Create a quantum curcuit with $ n=5 $ qubits.\n",
    "\n",
    "Set each qubit to $ \\ket{1} $.\n",
    "\n",
    "Repeat 4 times:\n",
    "<ul>\n",
    "    <li>Randomly pick a pair of qubits, and apply cx-gate (CNOT operator) on the pair.</li>\n",
    "</ul>\n",
    "\n",
    "Draw your circuit, and execute your program 100 times.\n",
    "\n",
    "Verify your measurement results by checking the diagram of the circuit. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Solution </h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import all necessary objects and methods for quantum circuits\n",
    "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer\n",
    "from qiskit.tools.visualization import matplotlib_circuit_drawer as drawer\n",
    "# import randrange for random choices\n",
    "from random import randrange\n",
    "\n",
    "n = 5\n",
    "m = 4\n",
    "\n",
    "values_of_qubits = [] # we keep a record of the qubits also in a list\n",
    "\n",
    "qreg1 =  QuantumRegister(n) # quantum register with n qubits\n",
    "creg1 = ClassicalRegister(n) # classical register with n bits\n",
    "\n",
    "mycircuit1 = QuantumCircuit(qreg1,creg1) # quantum circuit with quantum and classical registers\n",
    "\n",
    "# set each qubit to |1>\n",
    "for i in range(n):\n",
    "    mycircuit1.x(qreg1[i]) # apply x-gate (NOT operator)\n",
    "    values_of_qubits.append(1) # the value of each qubit is set to 1\n",
    "    \n",
    "# randomly pick m pairs of qubits\n",
    "for i in range(m):\n",
    "    controller_qubit = randrange(n)\n",
    "    target_qubit = randrange(n)\n",
    "    # controller and target qubits should be different\n",
    "    while controller_qubit == target_qubit: # if they are the same, we pick the target_qubit again\n",
    "        target_qubit = randrange(n)\n",
    "    # print our picked qubits\n",
    "    print(\"the indices of the controller and target qubits are\",controller_qubit,target_qubit)\n",
    "    # apply cx-gate (CNOT operator)\n",
    "    mycircuit1.cx(qreg1[controller_qubit],qreg1[target_qubit])\n",
    "    # we also trace the results\n",
    "    if values_of_qubits[controller_qubit] == 1: # if the value of the controller qubit is 1,\n",
    "        values_of_qubits[target_qubit] = 1 - values_of_qubits[target_qubit] # then flips the value of the target qubit \n",
    "        # remark that 1-x gives the negation of x\n",
    "    \n",
    "\n",
    "# measure the quantum register\n",
    "mycircuit1.measure(qreg1,creg1)\n",
    "\n",
    "print(\"Everything looks fine, let's continue ...\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# draw the circuit\n",
    "\n",
    "drawer(mycircuit1)\n",
    "# re-execute this cell if you DO NOT see the circuit diagram"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# execute the circuit 100 times in the local simulator\n",
    "\n",
    "job = execute(mycircuit1,Aer.get_backend('qasm_simulator'),shots=100)\n",
    "counts = job.result().get_counts(mycircuit1)\n",
    "\n",
    "# print the reverse of the outcome\n",
    "for outcome in counts:\n",
    "    reverse_outcome = ''\n",
    "    for i in outcome:\n",
    "        reverse_outcome = i + reverse_outcome\n",
    "    print(reverse_outcome,\"is observed\",counts[outcome],\"times\")\n",
    "\n",
    "# the value of the qubits should be as follows based on our own calculation\n",
    "print(values_of_qubits)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"task2\"></a>\n",
    "<h3>Task 2</h3>\n",
    "\n",
    "Our task is to learn the behaviour of the following quantum circut by doing experiments.\n",
    "\n",
    "Our circuit has two qubits. \n",
    "<ul>\n",
    "    <li> Apply Hadamard to the both qubits.\n",
    "    <li> Apply CNOT(first-qubit,second-qubit).\n",
    "    <li> Apply Hadamard to the both qubits.\n",
    "    <li> Measure the circuit.\n",
    "</ul>\n",
    "\n",
    "Iteratively initialize  the qubits to $ \\ket{00} $, $ \\ket{01} $, $ \\ket{10} $, and $ \\ket{11} $.\n",
    "\n",
    "Execute your program 100 times for each iteration, and then check the outcomes for each iteration. \n",
    "\n",
    "Verify that the overall circuit implements CNOT(second-qubit,first-qubit)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Solution </h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import all necessary objects and methods for quantum circuits\n",
    "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer\n",
    "from qiskit.tools.visualization import matplotlib_circuit_drawer as drawer\n",
    "\n",
    "all_inputs=['00','01','10','11']\n",
    "\n",
    "for input in all_inputs:\n",
    "    qreg2 =  QuantumRegister(2) # quantum register with 2 qubits\n",
    "    creg2 = ClassicalRegister(2) # classical register with 2 bits\n",
    "    mycircuit2 = QuantumCircuit(qreg2,creg2) # quantum circuit with quantum and classical registers\n",
    "    \n",
    "    #initialize the inputs\n",
    "    if input[0]=='1':\n",
    "        mycircuit2.x(qreg2[0]) # set the state of the first qubit to |1>\n",
    "    if input[1]=='1':\n",
    "        mycircuit2.x(qreg2[1]) # set the state of the second qubit to |1>\n",
    "\n",
    "    # apply h-gate to both qubits\n",
    "    mycircuit2.h(qreg2[0])\n",
    "    mycircuit2.h(qreg2[1])\n",
    "\n",
    "    # apply cx(first-qubit,second-qubit)\n",
    "    mycircuit2.cx(qreg2[0],qreg2[1])\n",
    "\n",
    "    # apply h-gate to both qubits\n",
    "    mycircuit2.h(qreg2[0])\n",
    "    mycircuit2.h(qreg2[1])\n",
    "\n",
    "    # measure both qubits\n",
    "    mycircuit2.measure(qreg2,creg2)\n",
    "    \n",
    "    # execute the circuit 100 times in the local simulator\n",
    "    job = execute(mycircuit2,Aer.get_backend('qasm_simulator'),shots=100)\n",
    "    counts = job.result().get_counts(mycircuit2)\n",
    "    for outcome in counts: # print the reverse of the outcomes\n",
    "        reverse_outcome = ''\n",
    "        for i in outcome:\n",
    "            reverse_outcome = i + reverse_outcome\n",
    "        print(\"our input is\",input,\"and\",reverse_outcome,\"is observed\",counts[outcome],\"times\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"task3\"></a>\n",
    "<h3>Task 3</h3>\n",
    "\n",
    "Our task is to learn the behaviour of the following quantum circut by doing experiments.\n",
    "\n",
    "Our circuit has two qubits. \n",
    "<ul>\n",
    "    <li> Apply CNOT(first-qubit,second-qubit).\n",
    "    <li> Apply CNOT(second-qubit,first-qubit).\n",
    "    <li> Apply CNOT(first-qubit,second-qubit).\n",
    "</ul>\n",
    "\n",
    "Iteratively initialize  the qubits to $ \\ket{00} $, $ \\ket{01} $, $ \\ket{10} $, and $ \\ket{11} $.\n",
    "\n",
    "Execute your program 100 times for each iteration, and then check the outcomes for each iteration. \n",
    "\n",
    "Verify that the overall circuit swaps the values of the first and second qubits:\n",
    "<ul>\n",
    "    <li> $\\ket{00} \\rightarrow \\ket{00} $ </li>\n",
    "    <li> $\\ket{01} \\rightarrow \\ket{10} $ </li>\n",
    "    <li> $\\ket{10} \\rightarrow \\ket{01} $ </li>\n",
    "    <li> $\\ket{11} \\rightarrow \\ket{11} $ </li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Solution </h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import all necessary objects and methods for quantum circuits\n",
    "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer\n",
    "from qiskit.tools.visualization import matplotlib_circuit_drawer as drawer\n",
    "\n",
    "all_inputs=['00','01','10','11']\n",
    "\n",
    "for input in all_inputs:\n",
    "    qreg3 =  QuantumRegister(2) # quantum register with 2 qubits\n",
    "    creg3 = ClassicalRegister(2) # classical register with 2 bits\n",
    "    mycircuit3 = QuantumCircuit(qreg3,creg3) # quantum circuit with quantum and classical registers\n",
    "    \n",
    "    #initialize the inputs\n",
    "    if input[0]=='1':\n",
    "        mycircuit3.x(qreg3[0]) # set the value of the first qubit to |1>\n",
    "    if input[1]=='1':\n",
    "        mycircuit3.x(qreg3[1]) # set the value of the second qubit to |1>\n",
    "\n",
    "    # apply cx(first-qubit,second-qubit)\n",
    "    mycircuit3.cx(qreg3[0],qreg3[1])\n",
    "    # apply cx(second-qubit,first-qubit)\n",
    "    mycircuit3.cx(qreg3[1],qreg3[0])\n",
    "    # apply cx(first-qubit,second-qubit)\n",
    "    mycircuit3.cx(qreg3[0],qreg3[1])\n",
    "    \n",
    "    mycircuit3.measure(qreg3,creg3)\n",
    "    \n",
    "    # execute the circuit 100 times in the local simulator\n",
    "    job = execute(mycircuit3,Aer.get_backend('qasm_simulator'),shots=100)\n",
    "    counts = job.result().get_counts(mycircuit3)\n",
    "    for outcome in counts: # print the reverse of the outcomes\n",
    "        reverse_outcome = ''\n",
    "        for i in outcome:\n",
    "            reverse_outcome = i + reverse_outcome\n",
    "        print(\"our input is\",input,\"and\",reverse_outcome,\"is observed\",counts[outcome],\"times\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
